﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using A2DFramework.EventService.SuperSocket.Core.Components;
using System.Timers;

namespace A2DFramework.EventService.SuperSocket.Core.Client
{
    public static class A2DTcpClientManager
    {
        private static string targetServerIp;
        private static int targetServerPort;
        private static A2DTcpClient a2dSocket;
        private static Action<string> funMsgReceived;
        private static Timer ensureSocketConnectedTimer=new Timer();
        private static double ensureSocketConnectedTimer_retryConnectInterval;
        private static Action<A2DTcpBroker> funReConnected;
        private static A2DTcpBroker broker=new A2DTcpBroker();
        private static object objLock_IsConnecting = new object();

        static A2DTcpClientManager()
        {
            ensureSocketConnectedTimer.Enabled = false;
            ensureSocketConnectedTimer.Elapsed += tmer_Elapsed;
        }

        public static A2DTcpBroker GetClientSocket(string serverIp, int serverPort, double retryConnectInterval, Action<A2DTcpBroker> funPerConnected)
        {
            if (a2dSocket != null && a2dSocket.IsConnecting())
            {
                return broker;
            }

            targetServerIp = serverIp;
            targetServerPort = serverPort;
            ensureSocketConnectedTimer_retryConnectInterval = retryConnectInterval;
            funReConnected = funPerConnected;

            Connect2Server();

            if (funReConnected != null)
                funReConnected(broker);

            return broker;
        }

        private static void Connect2Server()
        {
            lock (objLock_IsConnecting)
            {
                a2dSocket = new A2DTcpClient(targetServerIp, targetServerPort);

                if (funMsgReceived != null)
                    a2dSocket.NewMessageReceived += new A2DTcpClientMessageReceived(funMsgReceived);

                ensureSocketConnectedTimer.Enabled = false;
                ensureSocketConnectedTimer.Interval = ensureSocketConnectedTimer_retryConnectInterval;

                a2dSocket.Connect();
            }
        }
        private static void ReConnect2Server()
        {
            if (a2dSocket.IsConnecting())
                a2dSocket.Close();

            a2dSocket = null;

            a2dSocket = new A2DTcpClient(targetServerIp, targetServerPort);

            if (funMsgReceived != null)
                a2dSocket.NewMessageReceived += new A2DTcpClientMessageReceived(funMsgReceived);

            a2dSocket.Connect();
        }













        internal static void Send(string msg)
        {
            EnsureConnected();
            a2dSocket.Send(msg);
        }
        internal static void AttachEvent(Action<string> msgReceived)
        {
            funMsgReceived = msgReceived;

            EnsureConnected();

            a2dSocket.NewMessageReceived -= new A2DTcpClientMessageReceived(funMsgReceived);
            a2dSocket.NewMessageReceived += new A2DTcpClientMessageReceived(funMsgReceived);
        }





        private static void EnsureConnected()
        {
            while (!a2dSocket.IsConnecting())
                tmer_Elapsed(null, null);
        }

        private static void tmer_Elapsed(object sender, ElapsedEventArgs e)
        {
            ensureSocketConnectedTimer.Enabled = false;
            if (a2dSocket != null && a2dSocket.IsConnecting())
            {
                ensureSocketConnectedTimer.Enabled = true;
                return;
            }

            try
            {
                lock (objLock_IsConnecting)
                {
                    ReConnect2Server();
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
            }

            ensureSocketConnectedTimer.Enabled = true;
        }
    }
}
